﻿using DotNetty.Handlers.Logging;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using DotNettyExtensions.handler;
using EasyIot.Common;
using System;
using System.Net;
using System.Threading;

namespace DotNettyExtensions
{
    public class ServerIntance
    {
        private int port;
        private IProtocolHandler handle;
        private bool needtimeout;
        private static int READ_IDEL_TIME_OUT = 0; // 读超时
        private static int WRITE_IDEL_TIME_OUT = 0;// 写超时
        private static int ALL_IDEL_TIME_OUT = 5; // 所有超时
        //
        IEventLoopGroup bossGroup;
        //
        IEventLoopGroup workerGroup_tcp;
        IChannel boundChannel_tcp;
        //
        IChannel boundChannel_udp;

        public ServerIntance(int port, IProtocolHandler handle, bool needtimeout)
        {
            this.port = port;
            this.handle = handle;
            this.needtimeout = needtimeout;

            ThreadPool.QueueUserWorkItem(new WaitCallback(RunThread));
        }

        async void RunThread(object obj)
        { 
            bossGroup = new MultithreadEventLoopGroup(); 

            try
            {
                // tcp
                workerGroup_tcp = new MultithreadEventLoopGroup();
                var bootstrap_tcp = new ServerBootstrap();
                bootstrap_tcp.Group(bossGroup, workerGroup_tcp);
                bootstrap_tcp.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
                {
                    IChannelPipeline pipeline = channel.Pipeline;
                    if (needtimeout) pipeline.AddLast(new IdleStateHandler(READ_IDEL_TIME_OUT, WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT)); // 需要定时心跳包
                    pipeline.AddLast(new TCPHandler(handle));
                }));
                bootstrap_tcp.Channel<TcpServerSocketChannel>()
               .Option(ChannelOption.SoBacklog, 128)
               .ChildOption(ChannelOption.SoKeepalive, true);
                boundChannel_tcp = await bootstrap_tcp.BindAsync(port);
                Logger.Info("ServerIntance 监听tcp端口:" + port);
                //
                // udp  
                var bootstrap_udp = new Bootstrap();
                bootstrap_udp
                    .Group(bossGroup)
                        .Channel<SocketDatagramChannel>() //UDP连接方式
                        .Option(ChannelOption.SoBroadcast, true) //广播形式获取数据
                        .Option(ChannelOption.SoReuseaddr, true) //可以复用端口号
                        .Handler(new ActionChannelInitializer<IChannel>(channel =>
                        {
                            IChannelPipeline pipeline = channel.Pipeline;
                            if (needtimeout) pipeline.AddLast(new IdleStateHandler(READ_IDEL_TIME_OUT, WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT)); // 需要定时心跳包
                            pipeline.AddLast(new UDPHandler(handle));
                        }));
                boundChannel_udp = await bootstrap_udp.BindAsync(new IPEndPoint(IPAddress.Any, this.port)); //绑定本地端口号开始监听 

                Logger.Info("ServerIntance 监听udp端口:" + port);
            }
            catch (Exception ex)
            {
                Logger.Error("[Error] ServerIntance_RunThread,errmsg=" + ex.Message);
            }
        }

        void Close()
        {
            try
            {
                if (null != boundChannel_tcp) boundChannel_tcp.CloseAsync();
                if (null != boundChannel_udp) boundChannel_udp.CloseAsync();
            }
            catch (Exception ex)
            {
                Logger.Error("[Error] ServerIntance_Close,errmsg=" + ex.Message);
            }
            finally
            {
                bossGroup.ShutdownGracefullyAsync();
            }
        }
    }
}